package com.xxxx.spring.day03;

import com.xxxx.spring.day03.mapper.Mapper1;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Set;

public class A03Application {

    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config",Config.class);

        context.registerBean(ConfigurationClassPostProcessor.class); // @ComponentScan @Bean @Import @ImportResource
        context.registerBean(MapperScannerConfigurer.class,bd -> { // @MapperScanner
            bd.getPropertyValues().add("basePackage","com/xxxx/spring/day03/mapper");
        });
        // ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class,ComponentScan.class);
        // if(componentScan != null){
        //     for (String p : componentScan.basePackages()) {
        //         // 包名转成路径名
        //         // com.xxxx.spring.day03.component --> classpath*:com/xxxx/spring/day03/component/**/*.class
        //         System.out.println(p);
        //         String path = "classpath*:" + p.replace(".","/") + "/**/*.class";
        //         CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        //         Resource[] resources = context.getResources(path);
        //         AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
        //         for (Resource resource : resources) {
        //             System.out.println(resource);
        //             MetadataReader reader = factory.getMetadataReader(resource);
        //             // System.out.println("类名 :" + reader.getClassMetadata().getClassName());
        //             // System.out.println("是否加了 @Component: " + reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
        //             // System.out.println("是否加了 @Component 派生: " + reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
        //             AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
        //             if(annotationMetadata.hasAnnotation(Component.class.getName())
        //                     || annotationMetadata.hasMetaAnnotation(Component.class.getName())){
        //                 AbstractBeanDefinition bd = BeanDefinitionBuilder
        //                         .genericBeanDefinition(reader.getClassMetadata().getClassName())
        //                         .getBeanDefinition();
        //                 DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
        //                 // 根据 bean定义 去生成 bean 的名称 再进行bean的注册
        //                 String name = generator.generateBeanName(bd, beanFactory);
        //                 beanFactory.registerBeanDefinition(name,bd);
        //             }
        //         }
        //     }
        // }

        // 自定义的后置处理器
        // context.registerBean(ComponentScanPostProcessor.class);

        // CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        // MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/xxxx/spring/day03/Config.class"));
        // Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        // for (MethodMetadata method : methods) {
        //     System.out.println(method);
        //     String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
        //
        //     BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        //     builder.setFactoryMethodOnBean(method.getMethodName(),"config");
        //     // 构造方法的参数 工厂方法的参数 自动装配的模式 AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR
        //     builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        //     if(initMethod.length() > 0){
        //         builder.setInitMethodName(initMethod);
        //     }
        //     AbstractBeanDefinition bd = builder.getBeanDefinition();
        //     context.getDefaultListableBeanFactory().registerBeanDefinition(method.getMethodName(),bd);
        // }

        // 自定义的后置处理器
//        context.registerBean(AtBeanPostProcessor.class);
//
//        context.registerBean(MapperPostProcessor.class);

        // 初始化容器
        context.refresh();

        for(String name : context.getBeanDefinitionNames()){
            System.out.println(name);
        }
    }
}
